package session

import (
	"gitee.com/go-vulcanus/vulcanus/conf"
	"gitee.com/go-vulcanus/vulcanus/connection"
	"gitee.com/go-vulcanus/vulcanus/data"
	"gitee.com/go-vulcanus/vulcanus/utils"
	"gitee.com/go-vulcanus/vulcanus/utils/date"
	"github.com/google/wire"
	"strings"
	"sync"
)

var SessionProviderSet = wire.NewSet(NewSession)

type deviceInfo struct {
	DeviceCode    string `json:"name"`
	ConnectedType int    `json:"connectedType"`
	DeviceType    string `json:"deviceType"`
	LastCommTime  string `json:"lastCommTime"`
	GatewayAddr   string `json:"gatewayAddr"`
	Online        int    `json:"online"`
	ExpireTime    uint64 `json:"expireTime"`
}

// SessionManager 会话管理器
type SessionManager struct {
	deviceType     string
	registerOnline bool
	expireTime     uint64
	port           string
	sessions       sync.Map
	k              *data.Kafka
}

func NewSession(a *conf.App, c *conf.Server, k *data.Kafka) *SessionManager {
	s := &SessionManager{
		deviceType:     a.Device.DeviceType,
		registerOnline: a.Device.RegisterOnline,
		expireTime:     a.Device.ExpireTime,
		port:           strings.Split(c.Http.Addr, ":")[1],
		k:              k,
	}
	return s
}

func (s *SessionManager) Add(channel *connection.DeviceChannel) {
	if s.registerOnline {
		info := &deviceInfo{
			DeviceCode:    channel.DeviceCode,
			ConnectedType: 2,
			DeviceType:    s.deviceType,
			LastCommTime:  date.Now(),
			GatewayAddr:   utils.GetLocalIp() + ":" + s.port,
			Online:        1,
			ExpireTime:    s.expireTime * 60,
		}
		s.k.SendDeviceInfo(utils.ToJsonString(info))
	}
	s.sessions.Store(channel.DeviceCode, channel)
}

func (s *SessionManager) Get(deviceCode string) *connection.DeviceChannel {
	if load, ok := s.sessions.Load(deviceCode); ok {
		return load.(*connection.DeviceChannel)
	}
	return nil
}

func (s *SessionManager) Delete(deviceCode string) {
	if deviceChannel := s.Get(deviceCode); deviceChannel != nil {
		s.sessions.Delete(deviceCode)
		if s.registerOnline {
			info := &deviceInfo{
				DeviceCode:    deviceCode,
				ConnectedType: 2,
				DeviceType:    s.deviceType,
				Online:        0,
			}
			s.k.SendDeviceInfo(utils.ToJsonString(info))
		}
	}
}

func (s *SessionManager) ForEach(f func(key, value interface{}) bool) {
	s.sessions.Range(f)
}
